package cn.com.open.opensaas.scoreservice.logic;

import cn.com.open.opensaas.scoreservice.common.QuestionConstant;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class QuestionJudgeFactory {

    /**
     * 判分
     *
     * @param question
     * @param dbQuestion
     * @param itemMap
     */
    public void judge(Map<String, Object> question, Map<String, Object> dbQuestion, Map<String, Object> itemMap) {
        Integer questionType = (Integer) dbQuestion.get(QuestionConstant.ITEM_INNERTYPE);
        switch (questionType) {
            case QuestionConstant.QUESTION_TYPE_RADIO://单选
                judgeRadio(question, dbQuestion, itemMap);
                break;
            case QuestionConstant.QUESTION_TYPE_CHECKBOX://多选
                judgeCheckbox(question, dbQuestion, itemMap);
                break;
            case QuestionConstant.QUESTION_TYPE_JUDGE://判断
                judgeJudge(question, dbQuestion, itemMap);
                break;
            case QuestionConstant.QUESTION_TYPE_GAP://填空
                if ((Integer) dbQuestion.get(QuestionConstant.ITEM_SUBJECTIVE) == QuestionConstant.QUESTION_MOLD_OBJECTIVE) {//I32=0 客观题 判分  I32=1 主观题 不判分
                    judgeGap(question, dbQuestion, itemMap);
                }else{
                    itemMap.put(QuestionConstant.ITEM_IDENTIFIER, dbQuestion.get(QuestionConstant.ITEM_IDENTIFIER));
                    itemMap.put(QuestionConstant.STUDENT_ANSWER_SCORE, Double.valueOf(-1));
                    itemMap.put(QuestionConstant.SUB_ITEMS, dbQuestion.get(QuestionConstant.SUB_ITEMS));
                }
                break;
            case QuestionConstant.QUESTION_TYPE_MATCH://匹配
                judgeMatch(question, dbQuestion, itemMap);
                break;
            case QuestionConstant.QUESTION_TYPE_READ://阅读
                judgeRead(question, dbQuestion, itemMap);
                break;
            case QuestionConstant.QUESTION_TYPE_CLOZE://完型
                judgeCloze(question, dbQuestion, itemMap);
                break;
            default:
                itemMap.put(QuestionConstant.ITEM_IDENTIFIER, dbQuestion.get(QuestionConstant.ITEM_IDENTIFIER));
                itemMap.put(QuestionConstant.STUDENT_ANSWER_SCORE, 0.0);
                itemMap.put(QuestionConstant.SUB_ITEMS, dbQuestion.get(QuestionConstant.SUB_ITEMS));
                break;
        }
    }

    /**
     * 单选判分
     *
     * @param question
     * @param dbQuestion
     * @param itemMap
     */
    private void judgeRadio(Map<String, Object> question, Map<String, Object> dbQuestion, Map<String, Object> itemMap) {
        //将业务分值转为Double类型
        Double totalScore = Double.parseDouble(question.get(QuestionConstant.ITEM_SCORE) + "");
        if (equalList((List) dbQuestion.get(QuestionConstant.ITEM_CORRECT_ANSWER), (List) question.get(QuestionConstant.STUDENT_ANSWER))) {//比较正确答案与学生答案是否一致
            dbQuestion.put(QuestionConstant.STUDENT_ANSWER_SCORE, totalScore);//如果完成一致，得分
        } else {//不一致，不得分
            dbQuestion.put(QuestionConstant.STUDENT_ANSWER_SCORE, 0.0);
        }
        getItemMap(dbQuestion.get(QuestionConstant.ITEM_IDENTIFIER), dbQuestion.get(QuestionConstant.STUDENT_ANSWER_SCORE), dbQuestion.get(QuestionConstant.SUB_ITEMS), itemMap);
    }

    /**
     * 多选判分
     *
     * @param question
     * @param dbQuestion
     * @param itemMap
     */
    private void judgeCheckbox(Map<String, Object> question, Map<String, Object> dbQuestion, Map<String, Object> itemMap) {
        judgeRadio(question, dbQuestion, itemMap);
    }

    /**
     * 判断判分
     *
     * @param question
     * @param dbQuestion
     * @param itemMap
     */
    private void judgeJudge(Map<String, Object> question, Map<String, Object> dbQuestion, Map<String, Object> itemMap) {
        judgeRadio(question, dbQuestion, itemMap);
    }

    /**
     * 填空判分
     *
     * @param question
     * @param dbQuestion
     * @param itemMap
     */
    private void judgeGap(Map<String, Object> question, Map<String, Object> dbQuestion, Map<String, Object> itemMap) {
        //question I15答案   I9分数  dbQuestion I6答案   I7分数占比
        List<String> quesAnswerList = (List<String>) question.get(QuestionConstant.STUDENT_ANSWER);//获取学生答案列表
        Double dScore = Double.valueOf(question.get(QuestionConstant.ITEM_SCORE).toString());
        Integer score = dScore.intValue();//所有空总分数
        List<String> dbQuesAnswerList = (List<String>) dbQuestion.get(QuestionConstant.ITEM_OPTIONS);//获取库中答案列表
        List<String> dbQuesScorePercentList = (List<String>) dbQuestion.get(QuestionConstant.ITEM_CORRECT_ANSWER);//获取库中分值占比列表
        Double totalScore = 0.0;//用于统计整题总分
        List<Double> fillScore = new ArrayList<>();
        if(dbQuesAnswerList != null && !dbQuesAnswerList.isEmpty()){
            for (int i = 0 ; i < dbQuesAnswerList.size(); i++) {
                //获取客观填空题每个空的分值
                double eachEmptyScore = getScore(score, dbQuesAnswerList.size(),Double.valueOf(1), i).doubleValue();
                fillScore.add(eachEmptyScore);
            }
        }
        for (int i = 0; i < quesAnswerList.size(); i++) {//循环学生答案列表
            String quesAnswer = quesAnswerList.get(i);//循环中每个学生答案
            String dbQuesAnswer = dbQuesAnswerList.get(i);//与学生答案相同索引的库中答案
            String dbQuesScorePercent = dbQuesScorePercentList.get(i);//相应索引的分值占比
            String[] answers = {};//I6-数组 答案
            String[] scores = {};//I7-数组 分值比
            answers = dbQuesAnswer.split(QuestionConstant.QUESTION_SEPARATOR);
            scores = dbQuesScorePercent.split(QuestionConstant.QUESTION_SEPARATOR);
            for (int j = 0; j < answers.length; j++) {
                if (quesAnswer.equals(answers[j])) {
                    totalScore += getScore(score, dbQuesAnswerList.size(), Double.parseDouble(scores[j]), i).doubleValue();
                }
            }
        }
        dbQuestion.put(QuestionConstant.STUDENT_ANSWER_SCORE, totalScore);
        itemMap.put(QuestionConstant.FILL_SCORE,fillScore);
        getItemMap(dbQuestion.get(QuestionConstant.ITEM_IDENTIFIER), dbQuestion.get(QuestionConstant.STUDENT_ANSWER_SCORE), dbQuestion.get(QuestionConstant.SUB_ITEMS), itemMap);
    }

    /**
     * 匹配判分
     *
     * @param question
     * @param dbQuestion
     * @param itemMap
     */
    private void judgeMatch(Map<String, Object> question, Map<String, Object> dbQuestion, Map<String, Object> itemMap) {
        //获取学生Question的Sub子列表
        List<Map<String, Object>> questionSubList = (List<Map<String, Object>>) question.get(QuestionConstant.SUB_ITEMS);
        //获取库中Question的Sub子列表
        List<Map<String, Object>> dbQuestionSubList = (List<Map<String, Object>>) dbQuestion.get(QuestionConstant.SUB_ITEMS);
        Double d = Double.parseDouble(question.get(QuestionConstant.ITEM_SCORE) + "");
        Integer score = Integer.valueOf(d.intValue());//所有子题总分
        Double totalScore = 0.0;//用来统计整题所得分值
        List<Map<String, Object>> subList = new ArrayList<Map<String, Object>>();//用于存储结果集中Sub的list

        for (Integer i = 0; i < dbQuestionSubList.size(); i++) {//循环库中Question的Sub子列表
            Map<String, Object> subMap = new HashMap<String, Object>();//用于存储每个子题的得分结果信息
            Map<String, Object> dbQuestionSub = dbQuestionSubList.get(i);//循环中的每个子题
            String dbQuestionSubId = (String) dbQuestionSub.get(QuestionConstant.ITEM_IDENTIFIER);//循环中的第个子题Id

            boolean isExist = false;//判断子题是否存在标识
            for (Integer j = 0; j < questionSubList.size(); j++) {//循环学生Question的Sub子集
                Map<String, Object> questionSub = questionSubList.get(j);//循环中的每个子题
                String questionSubId = (String) questionSub.get(QuestionConstant.ITEM_IDENTIFIER);//循环中的每个子题Id
                if (questionSubId.equals(dbQuestionSubId)) {//判断学生子题Id与库中子题Id相等
                    isExist = true;
                    if (equalList((List) dbQuestionSub.get(QuestionConstant.ITEM_CORRECT_ANSWER), (List) questionSub.get(QuestionConstant.STUDENT_ANSWER))) {
                        Integer subScore = getScore(score, dbQuestionSubList.size(), 1.0, i);
                        dbQuestionSub.put(QuestionConstant.STUDENT_ANSWER_SCORE, subScore);
                    } else {
                        dbQuestionSub.put(QuestionConstant.STUDENT_ANSWER_SCORE, 0);
                    }
                    break;
                }
            }
            //Question在DBQuestion中没有的数据，给0
            if (!isExist) {
                dbQuestionSub.put(QuestionConstant.STUDENT_ANSWER_SCORE, 0);
            }
            subMap.put(QuestionConstant.ITEM_IDENTIFIER, dbQuestionSubId);
            subMap.put(QuestionConstant.STUDENT_ANSWER_SCORE, dbQuestionSub.get(QuestionConstant.STUDENT_ANSWER_SCORE));
            subList.add(subMap);
            totalScore += (Integer) dbQuestionSub.get(QuestionConstant.STUDENT_ANSWER_SCORE);
        }
        dbQuestion.put(QuestionConstant.STUDENT_ANSWER_SCORE, totalScore);
        getItemMap(dbQuestion.get(QuestionConstant.ITEM_IDENTIFIER), dbQuestion.get(QuestionConstant.STUDENT_ANSWER_SCORE), subList, itemMap);
    }

    /**
     * 阅读判分
     *
     * @param question
     * @param dbQuestion
     * @param itemMap
     */
    private void judgeRead(Map<String, Object> question, Map<String, Object> dbQuestion, Map<String, Object> itemMap) {
        judgeMatch(question, dbQuestion, itemMap);
    }

    /**
     * 完型判分
     *
     * @param question
     * @param dbQuestion
     * @param itemMap
     */
    private void judgeCloze(Map<String, Object> question, Map<String, Object> dbQuestion, Map<String, Object> itemMap) {
        judgeMatch(question, dbQuestion, itemMap);
    }

    /**
     * 拼接返回itemMap方法
     *
     * @param questionId
     * @param questionScore
     * @param subList
     * @param itemMap
     * @return
     */
    public void getItemMap(Object questionId, Object questionScore, Object subList, Map<String, Object> itemMap) {
        //拼接返回map,{"I1":"","I16":"","Sub":[]}
        itemMap.put(QuestionConstant.ITEM_IDENTIFIER, questionId);
        itemMap.put(QuestionConstant.STUDENT_ANSWER_SCORE, questionScore);
        itemMap.put(QuestionConstant.SUB_ITEMS, subList);
    }

    /**
     * 填空，完形，阅读获取分值方法
     *
     * @param score
     * @param subSize
     * @param scorePercent
     * @param index        当前索引，判断是否是最后一个
     * @return
     */
    public Integer getScore(Integer score, Integer subSize, Double scorePercent, Integer index) {
        Integer resultScore = 0;
        if (index < subSize - 1) {//不是最后一题，分值取整*百分比
            resultScore = (int) Math.floor(((score / subSize) * scorePercent));//向下取整，直接舍弃小数部分
        } else {//最后一题，(分值取整+余数)*百分比
            resultScore = (int) Math.floor(((score / subSize + score % subSize) * scorePercent));
        }
        return resultScore;
    }

    /**
     * 判断学生答案与库中存储答案是否一致
     *
     * @param answerList   学生答案列表
     * @param dbAnswerList 库中存储答案列表
     * @return
     */
    public boolean equalList(List dbAnswerList, List answerList) {
        //比较学生答案列表与为库中存储答案列表答案数量是否相等，不等则视为错误
        if (answerList.size() != dbAnswerList.size())
            return false;
        //循环判断库中答案列表是否包含学生答案，有一个不包含，则视为错误
        for (Object answer : answerList) {
            if (!dbAnswerList.contains(answer))
                return false;
        }
        return true;
    }

}
